using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;

namespace PropertyExpression.ControllableQuery.Demo
{
    public static class DB
    {
        private static readonly ConcurrentDictionary<string, string> dictionary = new ConcurrentDictionary<string, string>();

        public static SubQuery Insert<T>(string tableName, T param)
        {
            return new SubQuery(writer => {
                string value;
                if (!dictionary.TryGetValue(tableName, out value))
                {
                    var list = GetColumns(tableName).ToList();
                    value = "INSERT INTO " + tableName + " ("
                        + string.Join(", ", list) + ") VALUES ("
                        + string.Join(", ", list.Select(_ => "@" + _)) + ")";
                    dictionary[tableName] = value;
                }
                writer.WriteLiteral(value);
                writer.AppendParams(param);
            });
        }

        public static SubQuery Update<T>(string tableName, T param, string subText)
        {
            return new SubQuery(writer => {
                string value;
                if (!dictionary.TryGetValue(tableName, out value))
                {
                    var list = GetColumns(tableName).ToList();
                    value = "UPDATE " + tableName + " SET "
                        + string.Join(", ", list.Select(_ => _ + " = @" + _))
                        + subText;
                    dictionary[tableName] = value;
                }
                writer.WriteLiteral(value);
                writer.AppendParams(param);
            });
        }

        private static IEnumerable<string> GetColumns(string tableName)
        {
            using (var connection = new SqlConnection(QueryTest.ConnectionString))
            {
                connection.Open();
                using (var command = connection.CreateCommand())
                {
                    command.CommandText = @"
SELECT  columns.name
FROM    sys.columns
WHERE   columns.object_id = OBJECT_ID(@tableName)";
                    command.Parameters.Add(new SqlParameter
                    {
                        SqlDbType = SqlDbType.NVarChar,
                        Size = -1,
                        ParameterName = "@tableName",
                        Value = tableName
                    });
                    using (var reader = command.ExecuteReader())
                        while (reader.Read())
                            yield return (string)reader[0];
                }
            }
        }
    }
}